home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 17
/
CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso
/
CUCD
/
Programming
/
DiceSource
/
src
/
dutil
/
libtos.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-09-09
|
7KB
|
348 lines
/*
* (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
* use is allowed under the terms of the DICE-LICENSE FILE,
* DICE-LICENSE.TXT.
*/
/*
* LIBTOS.C
*
* This program takes two arguments, AMIGA.LIB, and an OUTPUT FILE,
* and systematically converts all references to the variables below
* from ABSOLUTE to A4-RELATIVE (Using Lattice's DATA-REL16 relocation
* info and symbol extensions).
*
* It converts absolute move's into an A4 relative move and a nop to
* take up the extra word which is now no longer used.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef AMIGA
#include <lib/version.h>
#else
#include <include/lib/version.h>
#endif
IDENT("libtos",".4");
DCOPYRIGHT;
short SymLens[64];
char *FixSymbols[64] = {
"_MathBase",
"_ClistBase",
"_ConsoleDevice",
"_DiskfontBase",
"_DOSBase",
"_SysBase",
"_GfxBase",
"_IconBase",
"_IntuitionBase",
"_LayersBase",
"_PotgoBase",
"_TimerBase",
"_TranslatorBase",
"_MathIeeeDoubBasBase",
"_MathTransBase",
"_ExpansionBase",
"_RomBootBase",
"_MathIeeeDoubTransBase",
/*
* 2.0 stuff (doesn't effect anything if you
* run on a 1.3 amiga.lib)
*/
"_BattClockBase",
"_BattMemBase",
"_CxBase",
"_GadToolsBase",
"_KeymapBase",
"_MathIeeeSingBasBase",
"_MathIeeeSingTransBase",
"_UtilityBase",
"_WorkbenchBase",
"_MiscBase",
"_IFFParseBase",
"_InputBase",
"_AslBase",
/*
* 3.0 stuff (doesn't effect anything if you
* run on a 1.3 or 2.0 amiga.lib)
*/
"_AmigaGuideBase",
"_BulletBase",
"_ColorWheelBase",
"_DataTypesBase",
"_DiskBase",
"_DTClassBase",
"_LocaleBase",
"_RexxSysBase",
NULL
};
short DDebug;
short Error;
typedef unsigned char ubyte;
typedef unsigned short uword;
typedef unsigned long ulong;
void InitSyms(void);
int ScanRelocations(long, long *, char *, long, char *, int);
#define MAXHUNKS 32
int
main(int ac, char **av)
{
FILE *fi;
FILE *fo;
short hunkno;
long *base;
long *scan;
long *bend;
long bytes;
InitSyms();
if (ac < 3) {
puts(Ident);
puts(DCopyright);
puts("libtos amiga.lib dlib:amigas.lib");
exit(1);
}
if (ac > 3)
DDebug = 1;
fi = fopen(av[1], "r");
if (fi == NULL) {
printf("couldn't open %s\n", av[1]);
exit(1);
}
fseek(fi, 0L, 2);
bytes = ftell(fi);
fseek(fi, 0L, 0);
base = malloc(bytes);
if (base == NULL) {
puts("ran out of memory");
exit(1);
}
fread((char *)base, bytes, 1, fi);
fclose(fi);
bend = base + (bytes >> 2);
for (scan = base; scan < bend;) {
ubyte *data;
long dlen;
short htype;
hunkno = 0;
if (*scan != 0x3E7) {
printf("Expected hunk_unit, got %08lx\n", *scan);
exit(1);
}
scan += scan[1] + 2;
/*
* scan the object module
*/
data = NULL;
dlen = 0;
htype = 0;
while (scan < bend && *scan != 0x3E7) {
ulong len;
switch((uword)*scan) {
case 0x3E8: /* HUNK_NAME */
scan += scan[1] + 2;
break;
case 0x3E9: /* HUNK_CODE */
case 0x3EA: /* HUNK_DATA */
data = (char *)(scan + 2);
dlen = scan[1] << 2;
if (*scan == 0x3EA)
htype = 1;
else
htype = 2;
{
++hunkno;
}
scan += scan[1] + 2;
break;
case 0x3EB: /* HUNK_BSS */
htype = 0;
scan += 2;
break;
case 0x3EC: /* HUNK_RELOC32 */
case 0x3ED: /* HUNK_RELOC16-PC */
case 0x3EE: /* HUNK_RELOC8 */
case 0x3F8: /* HUNK_RELOC16-D (special) */
++scan;
while (*scan)
scan += *scan + 2;
++scan;
break;
case 0x3EF: /* HUNK_EXT */
case 0x3F0: /* HUNK_SYMBOL */
++scan;
while ((len = *scan) != 0) {
ubyte type = len >> 24;
long *base = scan;
len &= 0x00FFFFFF;
if (DDebug)
printf("extsym %3d %.*s\n", type, (int)(len*4), (char *)(scan + 1));
scan += len + 1;
switch(type) {
case 0: /* SYMB */
case 1: /* DEF */
case 2: /* ABS */
case 3: /* RES */
++scan; /* skip value */
break;
case 130: /* COMMON */
++scan; /* skip common size */
/* fall through */
case 129: /* REF32 */
if (type == 129 && htype == 2) {
if (ScanRelocations(scan[0], scan + 1, data, dlen, (char *)(base + 1), len*4))
*base = (*base & 0x00FFFFFF) | (134 << 24); /* convert from ABS32 to DATA-REL16 */
}
case 131: /* REF16 */
case 132: /* REF8 */
case 134: /* REF16D */
/* skip relocation info */
scan += scan[0] + 1;
break;
default:
printf("Symbol type %d unknown", type);
exit(1);
}
}
++scan; /* skip 0 terminator */
break;
case 0x3F1: /* HUNK_DEBUG */
scan += scan[1] + 2;
break;
case 0x3F2: /* HUNK_END */
data = NULL;
dlen = 0;
++hunkno;
++scan;
break;
default:
printf("Unknown hunk type $%08lx", *scan);
exit(1);
}
}
}
if (Error) {
puts("ERROR OCCURED, OUTPUT NOT WRITTEN");
return(1);
}
fo = fopen(av[2], "w");
if (fo == NULL) {
printf("couldn't create %s\n", av[2]);
return(1);
}
fwrite((char *)base, bytes, 1, fo);
fclose(fo);
return(0);
}
void
InitSyms()
{
short i;
for (i = 0; FixSymbols[i]; ++i) {
SymLens[i] = strlen(FixSymbols[i]);
}
}
int
ScanRelocations(entries, scan, data, dlen, name, len)
long entries;
long *scan;
char *data;
long dlen;
char *name;
int len;
{
printf("Relocation: %2ld relocations for symbol %-20.*s", entries, len, name);
{
short i;
static char Buf[256];
strncpy(Buf, name, len);
Buf[len] = 0;
for (i = 0; SymLens[i]; ++i) {
if (strcmp(FixSymbols[i], Buf) == 0)
break;
}
if (SymLens[i] == 0) {
printf("(%s %d not modified)\n", Buf, strlen(Buf));
return(0);
}
}
puts("(modifying)");
while (entries) {
long index = *scan;
uword *tscan;
uword opcode;
if (index < 0 || index > dlen - 4) {
printf("relocation index out of range: %ld/%ld\n", index, dlen);
Error = 1;
}
tscan = (uword *)(data + index - 2);
opcode = *tscan;
printf("\topcode %04x\n", opcode);
/*
* convert abs to off(A4) 0010 0000 0110 1100
*/
switch(opcode) {
case 0x2079: /* move.l abslong,A0 */
tscan[0] = 0x206C;
tscan[1] = tscan[2];
tscan[2] = 0x4E71;
break;
case 0x2C79: /* move.l abslong,A6 */
tscan[0] = 0x2C6C;
tscan[1] = tscan[2];
tscan[2] = 0x4E71;
break;
case 0xD1F9: /* adda.l abslong,A0 */
tscan[0] = 0xD1EC;
tscan[1] = tscan[2];
tscan[2] = 0x4E71;
break;
default:
printf("\tWarning, opcode not understood, could not modify\n");
Error = 1;
break;
}
++scan;
--entries;
}
return(1);
}